<template>
  <!-- 权限管理-角色列表 -->
  <div>
    <!-- 面包屑导航区域 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/welcome' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>权限管理</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片视图区域 -->
    <el-card>
      <el-row>
        <el-col>
          <el-button type="primary" @click="addRolesDialogFormVisible = true"
            >添加角色</el-button
          >
          <!-- 添加角色按钮的对话框 -->
          <el-dialog
            title="添加角色"
            :visible.sync="addRolesDialogFormVisible"
            width="50%"
            @close="addRolesDialogClose"
          >
            <el-form
              :model="addRolesList"
              status-icon
              :rules="addRolesFormRules"
              ref="addRolesFormRef"
              label-position="left"
              label-width="80px"
            >
              <el-form-item label="角色名称" prop="roleName">
                <el-input v-model="addRolesList.roleName"></el-input>
              </el-form-item>
              <el-form-item label="角色描述" prop="roleDesc">
                <el-input v-model="addRolesList.roleDesc"></el-input>
              </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
              <el-button @click="addRolesDialogFormVisible = false"
                >取 消</el-button
              >
              <el-button type="primary" @click="addRoles">确 定</el-button>
            </span>
          </el-dialog>
        </el-col>
      </el-row>
      <el-table :data="rolesList" style="width: 100%" border stripe>
        <!-- 展开项，显示角色对应的权限信息的 -->
        <el-table-column type="expand">
          <!-- 可以展开的地方，显示权限信息的 -->
          <template v-slot:default="scope">
            <!-- 官网：另外也可以为数组索引指定别名 (或者用于对象的键)，v-for,中index的作用 -->
            <el-row
              v-for="(tagone, index1) in scope.row.children"
              :key="tagone.id"
              :class="['bdbottom', index1 === 0 ? 'bdtop' : '', 'vcenter']"
            >
              <el-col :span="5">
                <el-tag closable @close="removeRightById(scope.row, tagone.id)">
                  {{ tagone.authName }}
                </el-tag>
                <i class="el-icon-caret-right"></i>
              </el-col>
              <el-col :span="19">
                <!-- 二级的el-row -->
                <el-row
                  v-for="(tagtwo, index2) in tagone.children"
                  :key="tagtwo.id"
                  :class="[index2 === 0 ? '' : 'bdtop', 'vcenter']"
                >
                  <el-col :span="8">
                    <el-tag
                      type="success"
                      closable
                      @close="removeRightById(scope.row, tagtwo.id)"
                    >
                      {{ tagtwo.authName }}
                    </el-tag>
                    <i class="el-icon-caret-right"></i>
                  </el-col>
                  <el-col :span="16">
                    <!-- 三级的el-row -->
                    <el-row>
                      <el-col
                        :span="6"
                        v-for="tagthree in tagtwo.children"
                        :key="tagthree.id"
                      >
                        <el-tag
                          type="warning"
                          closable
                          @close="removeRightById(scope.row, tagthree.id)"
                        >
                          {{ tagthree.authName }}
                        </el-tag>
                      </el-col>
                    </el-row>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <el-table-column type="index" label="#" width="40"></el-table-column>
        <el-table-column prop="roleName" label="角色名称"></el-table-column>
        <el-table-column prop="roleDesc" label="角色描述"></el-table-column>
        <el-table-column label="操作" width="300">
          <!-- 此scope为当前行角色的所有权限信息 -->
          <template v-slot:default="scope">
            <el-button
              type="primary"
              size="mini"
              icon="el-icon-edit"
              @click="showEditDialog(scope.row.id)"
            >
              编辑
            </el-button>
            <el-button
              type="danger"
              size="mini"
              icon="el-icon-delete"
              @click="removeRolesById(scope.row.id)"
            >
              删除
            </el-button>
            <el-button
              type="warning"
              size="mini"
              icon="el-icon-setting"
              @click="editRigthsDialog(scope.row)"
            >
              分配权限
            </el-button>
            <!-- 修改角色的弹出对话框 -->
            <el-dialog
              title="修改角色"
              :visible.sync="editRolesDialogVisible"
              width="50%"
              @close="editRolesDialogClose"
            >
              <el-form
                :model="addRolesList"
                status-icon
                :rules="editRolesRules"
                ref="editRolesRef"
                label-position="left"
                label-width="80px"
              >
                <el-form-item label="角色名称" prop="roleName">
                  <el-input v-model="addRolesList.roleName"></el-input>
                </el-form-item>
                <el-form-item label="角色描述" prop="roleDesc">
                  <el-input v-model="addRolesList.roleDesc"></el-input>
                </el-form-item>
              </el-form>
              <div slot="footer" class="dialog-footer">
                <el-button @click="editRolesDialogVisible = false"
                  >取 消</el-button
                >
                <el-button type="primary" @click="editRoles()">确 定</el-button>
              </div>
            </el-dialog>
            <!-- 分配权限按钮的弹出对话框 -->
            <el-dialog
              title="分配权限"
              :visible.sync="editRigthsDialogVisible"
              width="50%"
              @close="editRigthsDialogClose"
            >
              <!-- 树形结构 -->
              <el-tree
                :data="RightsList"
                show-checkbox
                default-expand-all
                node-key="id"
                ref="treeRef"
                highlight-current
                :props="defaultProps"
                :default-checked-keys="defKeys"
              >
              </el-tree>
              <span slot="footer">
                <el-button @click="editRigthsDialogVisible = false"
                  >取 消</el-button
                >
                <el-button type="primary" @click="allotRights"
                  >确 定
                </el-button>
              </span>
            </el-dialog>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script>
export default {
  data () {
    return {
      // 页面created时，角色列表信息
      rolesList: [],
      // 用来接收 添加角色的请求 返回的数据
      addRolesList: {
        roleId: '',
        roleName: '',
        roleDesc: ''
      },
      // 所有权限信息
      RightsList: [],
      // 添加角色的对话框是否显示的属性
      addRolesDialogFormVisible: false,
      // 修改角色的对话框是否显示的属性
      editRolesDialogVisible: false,
      // 分配权限的对话框是否显示的属性
      editRigthsDialogVisible: false,
      // el-tree中显示文本的规则
      defaultProps: {
        children: 'children',
        label: 'authName'
      },
      // 树形结构默认选中的节点Id值数组，本角色已经含有的权限应被选中(即数组中含有三级ID)
      defKeys: [],
      // 添加角色的表单的校验规则
      addRolesFormRules: {
        roleName: [{ required: true, message: '用户名不能为空', trigger: 'blur' }],
        roleDesc: [{ required: true, message: '用户名不能为空', trigger: 'blur' }]
      },
      // 编辑角色的表单的校验规则
      editRolesRules: {
        roleName: [{ required: true, message: '用户名不能为空', trigger: 'blur' }],
        roleDesc: [{ required: true, message: '用户名不能为空', trigger: 'blur' }]
      },
      // 通过editRigthsDialog()获取到到的角色id
      roleId: ''
    }
  },
  created () {
    this.getRolesList()
  },
  methods: {
    // 获取角色信心，以及对应角色的权限信息
    async getRolesList () {
      const { data: res } = await this.$http.get('roles')
      if (res.meta.status !== 200) {
        return this.$message.error(res.meta.msg)
      } else {
        this.rolesList = res.data
      }
    },
    // 重置添加角色的表单
    addRolesDialogClose () {
      this.addRolesDialogFormVisible = false
      this.$refs.addRolesFormRef.resetFields()
    },
    addRoles () {
      this.$refs.addRolesFormRef.validate(async valid => {
        if (valid) {
          // 校验通过，可以发送添加用户的请求
          const { data: res } = await this.$http.post('roles',
            { roleName: this.addRolesList.roleName, roleDesc: this.addRolesList.roleDesc })
          if (res.meta.status === 201) {
            this.$message.success(res.meta.msg + '!')
            this.addRolesList = res.data
            this.getRolesList()
          } else {
            this.$message.error(res.meta.msg + '!')
          }
          this.addRolesDialogFormVisible = false
        } else {
          this.$message.error('数据校验失败！')
          return false
        }
      })
    },
    // 关闭修改用户信息的对话框
    editRolesDialogClose () {
      this.editRolesDialogVisible = false
      this.$refs.editRolesRef.resetFields()
    },
    // 修改角色信息
    async showEditDialog (id) {
      this.editRolesDialogVisible = true
      const { data: res } = await this.$http.get(`roles/${id}`)
      if (res.meta.status === 200) {
        this.addRolesList = res.data
      } else {
        this.$message.error(res.meta.msg + res.meta.status)
        return false
      }
    },
    // 修改角色信息
    editRoles () {
      this.$refs.editRolesRef.validate(async valid => {
        if (valid) {
          // 校验通过，可以发送添加用户的请求
          const { data: res } = await this.$http.put(`roles/${this.addRolesList.roleId}`,
            { roleName: this.addRolesList.roleName, roleDesc: this.addRolesList.roleDesc })
          if (res.meta.status === 200) {
            this.$message.success(res.meta.msg + '!')
            this.getRolesList()
          } else {
            this.$message.error(res.meta.msg + '!')
          }
          this.editRolesDialogVisible = false
        } else {
          this.$message.error('数据校验失败！')
          return false
        }
      })
    },
    // 点击删除按钮，删除角色
    removeRolesById (id) {
      this.$MessageBox.confirm('此操作将永久删除该用户, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'error'
      }).then(async () => {
        // 发送请求，进行删除用户操作
        const { data: res } = await this.$http.delete(`roles/${id}`)
        if (res.meta.status === 200) {
          this.$message.success('删除成功!')
          this.getRolesList()
        } else {
          // 删除失败
          this.$message.error(res.meta.msg)
          return false
        }
      }).catch(() => {
        this.$message.info('已取消删除')
      })
    },
    // 删除角色指定权限,role.id:角色id，rightId:权限id
    removeRightById (role, rightId) {
      this.$MessageBox.confirm('此操作将永久删除本角色该权限, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'error'
      }).then(async () => {
        const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${rightId}`)
        this.$message.success(res.meta.msg)
        role.children = res.data
      }).catch(() => {
        this.$message.info('已取消删除')
      })
    },
    // 点击分配权限按钮的事件，进行分配权限操作
    async editRigthsDialog (role) {
      this.roleId = role.id
      // roel：当前角色的所有权限信息
      const { data: res } = await this.$http.get('rights/tree')
      this.RightsList = res.data
      // 调用递归函数获取所有三级节点的id，组成一个数组用来树形结构的默认选中
      this.getLeafKeys(role, this.defKeys)
      this.editRigthsDialogVisible = true
    },
    // 通过递归的形式，获取角色下所有三级权限的id，并保存到defkeys数组中
    getLeafKeys (node, arr) {
      // node:节点-判断是否为三级节点，arr:用来保存三级权限id的数据
      if (!node.children) {
        // 没有childre，为三级节点，将其id加到arr()数组中
        return arr.push(node.id)
      }
      node.children.forEach(item => {
        this.getLeafKeys(item, arr)
      })
    },
    editRigthsDialogClose () {
      // 关闭对话框之前清空保存角色权限信息的id数组
      this.defKeys = []
    },
    // 给某角色(ID)分配权限
    async allotRights () {
      // 存放树形结构所有半选和全选的节点的id
      const keys = [
        // ...数组展开符号，可以将数组展开
        ...this.$refs.treeRef.getCheckedKeys(),
        ...this.$refs.treeRef.getHalfCheckedKeys()
      ]
      const idStr = keys.join(',')
      // 发送请求
      const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, { rids: idStr })
      if (res.meta.status === 200) {
        // 更新成功，重新渲染数据
        this.$message.success(res.meta.msg)
        this.getRolesList()
      } else {
        this.$message.error(res.meta.msg)
      }
      this.editRigthsDialogVisible = false
    }
  }
}
</script>

<style lang="less" scoped>
.el-tag {
  margin: 7px;
}
.bdtop {
  border-top: 1px solid #eee;
}
.bdbottom {
  border-bottom: 1px solid #eee;
}
.vcenter {
  // 纵向对其，用于角色列表roles页面的tag标签
  display: flex;
  align-items: center;
}
</style>
